/*******************************************************************************
*
* Copyright (C) 2013 - 2015, Jeffery Jiang, <china_jeffery@163.com>.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
*
* Expect bugs
*
* Please use and enjoy. Please let me know of any bugs/mods/improvements
* that you have found/implemented and I will fix/incorporate them into this
* file.
*
*******************************************************************************/

#include "IPCManager.h"
#include "CmnHdr.hpp"

DWORD QueryIPCList(IPCDetail *pList, DWORD dwMaxItem) {
    DWORD dwRet = 0;
    HANDLE hFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TotalIPC), TEXT("IPCDETAIL_DF3A2693_440B_4226_88E7_6C9A1911AEBA"));

    if(!hFile)
        return 0;

    LPVOID pBuffer = (LPVOID)MapViewOfFile(hFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    TotalIPC *pTotalIPC = (TotalIPC *)pBuffer;

    if(!pBuffer || !pTotalIPC)
        return 0;

    if(!pList) {
        UnmapViewOfFile(pBuffer);
        return MAX_IPC_SERVER_ONE_PC;
    }

    for(DWORD i = 0; i < MAX_IPC_SERVER_ONE_PC && i < dwMaxItem; i++) {
        pList[i].dwProcessID = pTotalIPC->details[i].dwProcessID;
        StringCchCopyA(pList[i].szIPCName, MAX_PATH, pTotalIPC->details[i].szIPCName);
        StringCchCopyA(pList[i].szProcessName, MAX_PATH, pTotalIPC->details[i].szProcessName);
    }

    UnmapViewOfFile(pBuffer);

    return MAX_IPC_SERVER_ONE_PC;
}

BOOL AddIPCDetail(const IPCDetail &detail) {
    BOOL bRet = FALSE;
    HANDLE hFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TotalIPC), TEXT("IPCDETAIL_DF3A2693_440B_4226_88E7_6C9A1911AEBA"));

    if(!hFile)
        return FALSE;

    LPVOID pBuffer = (LPVOID)MapViewOfFile(hFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    TotalIPC *pTotalIPC = (TotalIPC *)pBuffer;

    if(!pBuffer || !pTotalIPC)
        return FALSE;

    DWORD i = 0;

    for(i = 0; i < MAX_IPC_SERVER_ONE_PC; i++) {
        if(strcmp(pTotalIPC->details[i].szIPCName, detail.szIPCName) == 0)
            break;
    }

    if(i == MAX_IPC_SERVER_ONE_PC) {
        for(i = 0; i < MAX_IPC_SERVER_ONE_PC; i++) {
            if(strlen(pTotalIPC->details[i].szIPCName) <= 0) {
                StringCchCopyA(pTotalIPC->details[i].szIPCName, MAX_PATH, detail.szIPCName);
                StringCchCopyA(pTotalIPC->details[i].szProcessName, MAX_PATH, detail.szProcessName);
                pTotalIPC->details[i].dwProcessID = detail.dwProcessID;

                bRet = TRUE;
                break;
            }
        }
    }

    UnmapViewOfFile(pBuffer);

    return bRet;
}

BOOL RemoveIPCDetail(const char *szIPCName) {
    BOOL bRet = FALSE;
    HANDLE hFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TotalIPC), TEXT("IPCDETAIL_DF3A2693_440B_4226_88E7_6C9A1911AEBA"));

    if(!hFile)
        return FALSE;

    LPVOID pBuffer = (LPVOID)MapViewOfFile(hFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    TotalIPC *pTotalIPC = (TotalIPC *)pBuffer;

    if(!pBuffer || !pTotalIPC)
        return FALSE;

    DWORD i = 0;

    for(i = 0; i < MAX_IPC_SERVER_ONE_PC; i++) {
        if(strcmp(pTotalIPC->details[i].szIPCName, szIPCName) == 0) {
            ZeroMemory(pTotalIPC->details[i].szIPCName, MAX_PATH + 1);
            ZeroMemory(pTotalIPC->details[i].szProcessName, MAX_PATH + 1);
            pTotalIPC->details[i].dwProcessID = 0;

            bRet = TRUE;
            break;
        }
    }

    UnmapViewOfFile(pBuffer);

    return bRet;
}

BOOL IPCNameAvailable(const char *szIPCName) {
    DWORD dwIPCNum = QueryIPCList(NULL, 0);

    if(dwIPCNum <= 0)
        return TRUE;

    BOOL bRet = TRUE;
    IPCDetail *pDetailds = new IPCDetail[dwIPCNum];

    if(QueryIPCList(pDetailds, dwIPCNum) > 0) {
        for(DWORD i = 0; i < dwIPCNum; i++) {
            if(strcmp(pDetailds[i].szIPCName, szIPCName) == 0) {
                bRet = FALSE;
                break;
            }
        }
    }

    SAFE_DELETE_ARRAY(pDetailds);

    return bRet;
}
